<?php
/**
 * @author jonathan <jo.link.noir@gmail.com>
 * @version 1.0: jo_link_noir
 * @date 26-05-2010
 */
class SW_Player implements Serializable, ArrayAccess
{
	/** @var string */
	const INDEX = 'player';


	/** @var array {SW_Player, ..}*/
	protected static $players = array();


	/** @var ArrayIterator : tableau des données insérés*/
	protected $data = null;

	/** @var int */
	protected $id;

	/** @var int */
	protected $race;

	/** @var string */
	protected $name;

	/** @var int */
	protected $idClan;

	/** @var string */
	protected $nameClan;

	/**
	 * @param int $id
	 * @param int $race
	 * @param string $name
	 * @param int $idClan = 0
	 * @param string $nameClan = ''
	 */
	protected function __construct($id, $race, $name, $idClan = 0, $nameClan = '')
	{
		$this->id = (int)$id;
		$this->race = (int)$race;
		$this->name = $name;
		$this->idClan = (int)$idClan;
		$this->nameClan = $nameClan;

		if (!$this->data)
			$this->data = new ArrayIterator(array(), ArrayIterator::ARRAY_AS_PROPS);
		self::$players[$this->id] = $this;
	}

	/**
	 * Récupère l'objet SW_Player du joueur ou le crée s'il n'existe pas
	 * @param int $id
	 * @param int $race
	 * @param string $name
	 * @param int $idClan = 0
	 * @param string $nameClan = ''
	 * @return SW_Player
	 */
	static public function factory($id, $race, $name, $idClan = 0, $nameClan = '')
	{
		return isset(self::$players[$id])
			? self::$players[$id]
			: new static($id, $race, $name, $idClan, $nameClan);
	}

	/**
	 * @param int $id
	 * @return SW_Player|null
	 */
	static public function getFactory($id)
	{
		return isset(self::$players[$id]) ? self::$players[$id] : null;
	}

	/**
	 * Vérifie si l'objet SW_Player existe
	 * @param int $id
	 * @return bool
	 */
	static public function existsFactory($id)
	{
		return isset(self::$players[$id]);
	}

	/**
	 * @return array : {SW_Player, ...}
	 */
	static public function getPlayers()
	{
		return self::$players;
	}

	/**
	 * Accesseur pour l'id du joueur
	 * @return int
	 */
	public function getId()
	{
		return $this->id;
	}

	/**
	 * accesseur pour la race
	 * @return int
	 */
	public function getRace()
	{
		return $this->race;
	}

	/**
	 * accesseur pour le nom
	 * @return string
	 */
	public function getName()
	{
		return $this->name;
	}

	/**
	 * Accesseur pour l'id du clan
	 * @return int
	 */
	public function getIdClan()
	{
		return $this->idClan;
	}

	/**
	 * Accesseur pour le nom du clan
	 * @return int
	 */
	public function getNameClan()
	{
		return $this->nameClan;
	}

	/**
	 * @param int $idClan
	 */
	public function setIdClan($idClan)
	{
		$this->idClan = $idClan;
	}

	/**
	 * @param int $nameClan
	 */
	public function setNameClan($nameClan)
	{
		$this->nameClan = $nameClan;
	}

	/**
	 * Récupère l'instance si l'objet player existe et si l'instance existe
	 * @param mixed $instance
	 * @param int $idPlayer
	 * @return mixed|null
	 */
	static public function getInstancePlayerIfExists($instance, $idPlayer)
	{
		if (isset(self::$players[$idPlayer]))
		{
			$self = self::$players[$idPlayer];
			if ($self->offsetExists($instance))
				return $self->offsetGet($instance);
		}
		return null;
	}

	/**
	 * Assigne $value avec comme clé $offset
	 * @param mixed $offset
	 * @param mixed $value
	 */
	public function offsetSet($offset, $value)
	{
		/*if (is_array($value))
			$this->data->$offset = new ArrayIterator($value, ArrayIterator::ARRAY_AS_PROPS);
		else*/
			$this->data->$offset = $value;
	}

	/**
	 * Récupère la valeur qui à comme clé $offset
	 * @param mixed $offset
	 */
	public function offsetGet($offset)
	{
		return isset($this->data->$offset)
			? $this->data->$offset
			: $this->data->$offset = $this->initOffset($offset);
	}

	/**
	 * TODO ???
	 * Initialise l'offset de $data s'il n'existe pas.
	 * @param mixed $offset
	 * @return mixed
	 */
	protected function initOffset($offset)
	{
		return null;
	}

	/**
	 * Indique si la position à $offset existe
	 * @param mixed $offset
	 */
	public function offsetExists($offset)
	{
		return isset($this->data->$offset);
	}

	/**
	 * Supprime la position indiqué par $offset
	 * @param mixed $offset
	 */
	public function offsetUnset($offset)
	{
		unset($this->data->$offset);
	}

	/**
	 * Supprime en mémoire les autres joueurs
	 */
	protected function purgeOtherPlayer()
	{
		foreach (self::$players as $id => $player)
			if ($this->id !== $id)
				$player->__destruct();
	}

	/**
	 * Détruit les données lié au joueur mais garde la donnée db
	 */
	public function __destruct()
	{
		unset(self::$players[$this->id]);
		foreach ($this->data as $data)
			$data->__destruct();
	}

	/**
	 * @return string
	 */
    public function serialize()
	{
        return serialize($this->toArray());
    }

	/**
	 * @param string $data
	 */
    public function unserialize($data)
	{
        $this->toPlayer(unserialize($data));
    }

	/**
	 * Transforme les données en array pour être utilisé dans serialize
	 * @return array
	 */
	protected function toArray()
	{
		return array($this->id, $this->race, $this->name, $this->idClan, $this->nameClan);
	}

	/**
	 * Utilise le constructeur pour crée un player
	 */
	protected function toPlayer(array $data)
	{
		$this->__construct($data[0], $data[1], $data[2], $data[3], $data[4]);
	}
}